#ifndef LIST_H
#define LIST_H

#include <iostream>
#include <cstdlib>

template <typename T> class List {
private:
	struct element {
		T data;
		element * next;
	};
	
	element * head;
		
	// Метод проверяющий пуст ли список. Возвращает true если пуст и false иначе
	bool empty() const;
	
	// Запрет использования конструктора копирования и оператора присваивания
	List(const List& list);
	List& operator=(const List& list);
public:
	// Конструктор по умолчанию
	List();
	
	// Деструктор, освобождающий всю выделенную память
	~List();

	// Операция вставки элемента в начала списка
	void push_front(const T& value);
	
	// Операция удаления первого элемента списка
	void pop_front();
	
	// Операция вставки элемента в конец списка
	void push_back(const T& value);
	
	// Операция удаления последнего элемента списка
	void pop_back();

	// Распечатывает список
	void print();
	
	// класс Итератор, позволяющий перебирать содержимое списка
	class Iterator {
	public:
		Iterator(element * e) {
			this->e = e;
		}
		// оператор для обращения к простым типам
		T operator *() {
			return e->data;
		}
		
		// оператор для обращения к структурам или классам
		T * operator ->() {
			return &e->data;
		}
		
		// преинкрементный оператор перехода на новый элемент
		Iterator& operator++() {
			e = e->next;
			return *this;
		}
		
		// постинкремент оператор перехода на новый элемент
		Iterator operator++(int) {
			List<T>::Iterator i = *this;
			++(*this);
			return i;
		}
				
		// проверка на равенство двух итераторов, 
		// возвращает true если итераторы указывают на один и тот же элемент
		// false иначе
	    bool operator == (const Iterator& i) const {
			return e == i.e;
		}
		
		// проверка на то, что два итератора не совпадают
		bool operator != (const Iterator& i) const {
			return e != i.e;
		}
	private:
		element * e;			
	};

	// Возвращает итератор на начало списка
	Iterator begin() {
		return Iterator( head );
	}
	
	// Возвращает итератор на конец списка
	Iterator end()  {
		return Iterator( NULL );
	}
};

#endif